package com.zwps.biz.domain.extra.netease;

import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zwps.common.core.exception.UserActionException;

import lombok.Getter;
import lombok.Setter;

import java.security.MessageDigest;
import java.util.Date;
import java.util.HashMap;

/**
 * @author shanwen
 * @description:
 * @date 2023-08-02
 * @ClassName NeteasePhoneMessageHelper
 */
public class NeteasePhoneMessageHelper {

    private final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
            'f' };

    private final String appKey;
    private final String appSecret;
    private final String serverUrl;
    private final String nonce;

    public NeteasePhoneMessageHelper(String appKey, String appSecret, String serverUrl, String nonce) {
        this.appKey = appKey;
        this.appSecret = appSecret;
        this.serverUrl = serverUrl;
        this.nonce = nonce;
    }

    private final ObjectMapper objectMapper = new ObjectMapper();

    public void send(NeteasePhoneMessage message) {
        String mobiles;
        String params;
        try {
            mobiles = objectMapper.writeValueAsString(message.getMobiles());
            params = objectMapper.writeValueAsString(message.getParams());
        } catch (JsonProcessingException e1) {
            e1.printStackTrace();
            throw new UserActionException("发送短信失败");
        }

        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("templateid", message.getTemplateid());
        map.put("mobiles", mobiles);
        map.put("params", params);
        HttpRequest request = HttpUtil.createPost(serverUrl);
        setRequestHeader(request).form(map);

        try {
            HttpResponse response = request.execute();
            ResponseMessage rm = objectMapper.readValue(response.body(), ResponseMessage.class);
            if (rm.getCode() != 200) {
                throw new UserActionException(rm.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new UserActionException("发送短信失败");
        }
    }

    public String sendCode(NeteasePhoneCodeMessage message) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("templateid", message.getTemplateid());
        map.put("mobile", message.getMobile());
        map.put("codeLen", message.getCodeLen());
        HttpRequest request = HttpUtil.createPost(serverUrl);
        setRequestHeader(request).form(map);
        try {
            HttpResponse response = request.execute();
            ResponseMessage rm = objectMapper.readValue(response.body(), ResponseMessage.class);
            if (rm.getCode() == 200) {
                return rm.getObj();
            }
            if (rm.getCode() == 416) {
                throw new UserActionException("一天最多接收10条验证码");
            }
            throw new UserActionException("发送失败");
        } catch (UserActionException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new UserActionException("发送短信失败");
        }
    }

    public void verifyCode(String mobile, String code) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("mobile", mobile);
        map.put("code", code);
        HttpRequest request = HttpUtil.createPost(serverUrl);
        setRequestHeader(request).form(map);
        try {
            HttpResponse response = request.execute();
            ResponseMessage rm = objectMapper.readValue(response.body(), ResponseMessage.class);
            if (rm.getCode() != 200) {
                throw new UserActionException(rm.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new UserActionException("发送短信失败");
        }
    }

    private HttpRequest setRequestHeader(HttpRequest request) {
        request.setConnectionTimeout(15000);
        request.setReadTimeout(30000);
        String curTime = String.valueOf((new Date()).getTime() / 1000L);
        /*
         * 参考计算CheckSum的java代码，在上述文档的参数列表中，有CheckSum的计算文档示例
         */
        String checkSum = getCheckSum(appSecret, nonce, curTime);
        request.header("AppKey", appKey);
        request.header("Nonce", nonce);
        request.header("CurTime", curTime);
        request.header("CheckSum", checkSum);
        request.header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8");
        request.header("Access-Control-Allow-Origin", "*");
        return request;
    }

    // 计算并获取CheckSum
    private String getCheckSum(String appSecret, String nonce, String curTime) {
        return encode("sha1", appSecret + nonce + curTime);
    }

    private String encode(String algorithm, String value) {
        if (value == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            messageDigest.update(value.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    // {"code":200,"msg":"sendid","obj":63118}
    @Getter
    @Setter
    public static class ResponseMessage {
        Integer code;
        String msg;
        String obj;
    }
}
